package com.shop.cereshop.app.tencent.im.utils;

import com.shop.cereshop.app.tencent.im.model.redpacket.CreateRedPacketParam;
import com.shop.cereshop.app.tencent.im.model.redpacket.ReceiveRedPacketDTO;
import com.shop.cereshop.app.tencent.im.model.redpacket.RedPacket;
import com.shop.cereshop.app.exception.BusinessException;
import com.shop.cereshop.commons.constant.CoReturnFormat;
import com.shop.cereshop.commons.result.Result;
import com.shop.cereshop.commons.tencent.im.enums.redpacket.RedPacketStatusEnum;
import com.shop.cereshop.commons.tencent.im.enums.redpacket.RedPacketTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;

/**
 * @description: 红包工具类
 * @author zdd
 * @date 2025/9/4 11:28
 * @version 1.0
 */
@Slf4j
public class RedPacketUtils {

    /** 默认祝福语 */
    public static final String DEFAULT_BLESSING = "恭喜发财，大吉大利！";
    /** 四舍五入 */
    private static final RoundingMode ROUND_MODE = RoundingMode.HALF_UP;
    /** 金额精度（元为单位，保留2位小数） */
    private static final int SCALE = 2;
    /** 最小金额占总金额比例（1%） */
    private static final BigDecimal MIN_RATIO = new BigDecimal("0.01");
    /** 最大金额占总金额比例（30%） */
    private static final BigDecimal MAX_RATIO = new BigDecimal("0.3");
    /** 极端情况下的最大金额占总金额比例（60%） */
    private static final BigDecimal EXTREME_MAX_RATIO = new BigDecimal("0.6");
    /** 红包最小个数 */
    public static final Integer MIN_COUNT = 1;
    /** 群发红包最大个数 */
    public static final Integer GROUP_RED_PACKET_MAX_COUNT = 100;
    /** 红包最小金额 */
    public static final BigDecimal MIN_AMOUNT = new BigDecimal("0.01");
    /** 单聊红包最大金额 */
    public static final BigDecimal SINGLE_RED_PACKET_MAX_AMOUNT = new BigDecimal("200.00");
    /** 群发红包最大金额 */
    public static final BigDecimal GROUP_RED_PACKET_MAX_AMOUNT = new BigDecimal("2000.00");



    /**
     * 验证创建红包参数
     * @throws BusinessException 业务异常
     */
    public static Result<Object> validateCreateRedPacketParams(CreateRedPacketParam packetParam) {
        if (packetParam.getType() == null) {
            return Result.custom(CoReturnFormat.PARAM_INVALID, "红包类型不能为空");
        }
        if (packetParam.getType() < RedPacketTypeEnum.NORMAL.getCode() ||  packetParam.getType() > RedPacketTypeEnum.EXCLUSIVE.getCode()) {
            return Result.custom(CoReturnFormat.PARAM_INVALID, "红包类型错误");
        }
        if (packetParam.getCount() == null || packetParam.getCount() < MIN_COUNT) {
            return Result.custom(CoReturnFormat.PARAM_INVALID, "红包个数不能为空且必须大于0");
        }
        BigDecimal amount = packetParam.getAmount();
        if (amount == null) {
            return Result.custom(CoReturnFormat.PARAM_INVALID, "红包金额不能为空");
        }
        if (amount.compareTo(MIN_AMOUNT) < 0) {
            return Result.custom(CoReturnFormat.PARAM_INVALID, "红包金额不能小于" + MIN_AMOUNT +"元");
        }
        boolean isGroup = StringUtils.isBlank(packetParam.getGroupId())
                && (RedPacketTypeEnum.NORMAL.getCode().equals(packetParam.getType())
                    || RedPacketTypeEnum.LUCKY.getCode().equals(packetParam.getType()));
        if(isGroup) {
            return Result.custom(CoReturnFormat.PARAM_INVALID, "groupId不能为空");
        }
        // 单聊红包，默认设置红包个数为1、类型为专属红包
        if (StringUtils.isBlank(packetParam.getGroupId())) {
//            packetParam.setCount(MIN_COUNT);
            packetParam.setType(RedPacketTypeEnum.EXCLUSIVE.getCode());
            if (amount.compareTo(SINGLE_RED_PACKET_MAX_AMOUNT) > 0) {
                return Result.custom(CoReturnFormat.PARAM_INVALID, "红包金额不能超过" + SINGLE_RED_PACKET_MAX_AMOUNT + "元");
            }
            if (packetParam.getCount().compareTo(MIN_COUNT) > 0) {
                return Result.custom(CoReturnFormat.PARAM_INVALID, "单聊红包个数不能超过" + MIN_COUNT + "个");
            }
        }
        // 群组红包
        if (StringUtils.isNotBlank(packetParam.getGroupId())) {
            if (packetParam.getCount() > GROUP_RED_PACKET_MAX_COUNT) {
                return Result.custom(CoReturnFormat.PARAM_INVALID, "红包个数不能超过" + GROUP_RED_PACKET_MAX_COUNT +"个");
            }
            if (amount.compareTo(GROUP_RED_PACKET_MAX_AMOUNT) > 0) {
                return Result.custom(CoReturnFormat.PARAM_INVALID, "红包金额不能超过" + GROUP_RED_PACKET_MAX_AMOUNT + "元");
            }
        }
        return Result.success();
    }

    /**
     * 判断红包领取状态 (此方法可考虑移至 RedPacketService 接口或工具类中，供复用)
     * @param redPacket 红包信息
     * @param recordCount 当前领取人领取记录数量
     * @return Result
     */
    public static Result<Object> judgeRedPacketReceiveStatus(RedPacket redPacket, int recordCount) {
        if (recordCount > 0) {
            return Result.custom(CoReturnFormat.FAIL, "您已领取红包，请勿重复领取!");
        }
        if (RedPacketStatusEnum.CREATE.getCode().equals(redPacket.getStatus())) {
            log.warn("红包状态为创建，还未发送，暂时无法领取! packetId: {}", redPacket.getPacketId());
            return Result.custom(CoReturnFormat.FAIL, "红包暂时无法领取!");
        }
        boolean expired = (redPacket.getExpireTime() != null && redPacket.getExpireTime().isBefore(LocalDateTime.now()))
                || RedPacketStatusEnum.EXPIRED.getCode().equals(redPacket.getStatus());
        if (expired) {
            return Result.custom(CoReturnFormat.FAIL, "红包已过期!");
        }
        if (RedPacketStatusEnum.REFUNDED.getCode().equals(redPacket.getStatus())) {
            return Result.custom(CoReturnFormat.FAIL, "红包已退款，无法领取!");
        }
        boolean completed = RedPacketStatusEnum.COMPLETED.getCode().equals(redPacket.getStatus())
                || redPacket.getRemainCount() == null
                || redPacket.getRemainCount() < 1L
                || redPacket.getRemainAmount() == null
                || redPacket.getRemainAmount().compareTo(BigDecimal.ZERO) <= 0;
        if (completed) {
            return Result.custom(CoReturnFormat.FAIL, "手慢了，红包已领完!");
        }
        return Result.success();
    }

    /**
     * 构建红包领取DTO
     *
     * @param redPacket 红包信息
     * @param receiverId 领取人ID
     * @param receiverName 领取人名称
     * @param allocatedAmount 领取金额
     * @return 红包领取DTO
     */
    public static ReceiveRedPacketDTO buildRedPacketDTO(RedPacket redPacket, String receiverId, String receiverName, BigDecimal allocatedAmount) {
        ReceiveRedPacketDTO packetDTO = new ReceiveRedPacketDTO();
        packetDTO.setPacketId(redPacket.getPacketId());
        packetDTO.setReceiverId(receiverId);
        packetDTO.setReceiverName(receiverName);
        // 领取数量为1
        packetDTO.setReceiveCount(1);
        if (StringUtils.isBlank(redPacket.getGroupId())) {
            //  单聊红包，金额置零，状态改为已领完 (根据原逻辑，这里应该是总金额?)
            packetDTO.setReceiveAmount(redPacket.getTotalAmount());
            packetDTO.setStatus(RedPacketStatusEnum.COMPLETED.getCode());
        } else {
            // 群聊红包，减去领取金额，如果当前剩余数量小于等于1，状态改为已领完，否则改为未领完
            packetDTO.setReceiveAmount(allocatedAmount);
            if (redPacket.getRemainCount() <= 1L) {
                packetDTO.setStatus(RedPacketStatusEnum.COMPLETED.getCode());
            } else {
                packetDTO.setStatus(RedPacketStatusEnum.NOT_FINISHED.getCode());
            }
        }
        return packetDTO;
    }


    // =========================普通红包、拼手气红包金额算法============================================================================================

    /**
     * 获取红包分配金额列表
     *
     * @param type 红包类型
     * @param amount 金额
     * @param count  红包个数
     * @return 红包金额列表（均为正数，总和=总金额）
     */
    public static List<BigDecimal> getRedPacketAmounts(Integer type, BigDecimal amount, int count) {
        // 普通红包
        if (RedPacketTypeEnum.NORMAL.getCode().equals(type)) {
            return getNormalRedPacketAmountsV2(amount, count);
        }
        // 拼手气红包
        if (RedPacketTypeEnum.LUCKY.getCode().equals(type)) {
            return getRandomRedPacketAmounts(amount, count);
        }
        // 专属红包
        return Collections.singletonList(amount);
    }

    /**
     * 普通红包：平均分配（最后一个红包处理精度误差）
     *
     * @param totalAmount 总金额
     * @param totalCount  红包总个数
     * @return 红包金额列表（均为正数，总和=总金额）
     */
    public static List<BigDecimal> getNormalRedPacketAmounts(BigDecimal totalAmount, int totalCount) {
        List<BigDecimal> packets = new ArrayList<>(totalCount);
        // 处理特殊情况：只有一个红包
        if (totalCount == 1) {
            packets.add(totalAmount);
            return packets;
        }
        // 计算平均金额（前n-1个红包）
        BigDecimal avgAmount = totalAmount.divide(new BigDecimal(totalCount), SCALE, RoundingMode.DOWN);
        // 前n-1个红包分配平均金额
        for (int i = 0; i < totalCount - 1; i++) {
            packets.add(avgAmount);
        }
        // 最后一个红包：总金额 - 前n-1个红包总和（处理精度误差）
        BigDecimal lastAmount = totalAmount.subtract(avgAmount.multiply(new BigDecimal(totalCount - 1)));
        packets.add(lastAmount);
        return packets;
    }

    /**
     * 普通红包：平均分配
     *
     * @param amount 单个金额
     * @param count  红包个数
     * @return 红包金额列表（均为正数，总和=总金额）
     */
    public static List<BigDecimal> getNormalRedPacketAmountsV2(BigDecimal amount, int count) {
        List<BigDecimal> packets = new ArrayList<>(count);
        List<BigDecimal> list = Collections.nCopies(count, amount);
        packets.addAll(list);
        return packets;
    }

    /**
     * 拼手气红包：满足1%最小+30%最大限制的随机分配（极端情况下允许60%）
     * 采用双向限制策略，确保每一步分配都考虑后续红包的 min/max 限制。
     *
     * @param totalAmount 总金额
     * @param totalCount  红包总个数
     * @return 红包金额列表（每个金额在[min, max]之间，总和=总金额）
     */
    public static List<BigDecimal> getRandomRedPacketAmounts(BigDecimal totalAmount, int totalCount) {
        List<BigDecimal> packets = new ArrayList<>(totalCount);

        // 处理特殊情况：只有一个红包
        if (totalCount == 1) {
            packets.add(totalAmount);
            return packets;
        }

        // 剩余待分配金额（保留2位小数，避免精度累积）
        BigDecimal remainingAmount = totalAmount.setScale(SCALE, ROUND_MODE);
        // 剩余待分配个数
        int remainingCount = totalCount;

        // 计算单个红包的全局最小、最大限制金额
        BigDecimal globalMinSingleAmount = totalAmount.multiply(MIN_RATIO).setScale(SCALE, ROUND_MODE);
        BigDecimal globalMaxSingleAmount = totalAmount.multiply(MAX_RATIO).setScale(SCALE, ROUND_MODE);

        // 确保全局最小金额不小于系统最小金额限制
        if (globalMinSingleAmount.compareTo(MIN_AMOUNT) < 0) {
            globalMinSingleAmount = MIN_AMOUNT;
        }

        // 预校验：确保最小金额总和不超过总金额（避免后续分配失败）
        BigDecimal minTotalAmount = globalMinSingleAmount.multiply(new BigDecimal(totalCount));
        if (totalAmount.compareTo(minTotalAmount) < 0) {
            throw new RuntimeException("拼手气红包总金额需不小于" + minTotalAmount + "元（每个至少" + globalMinSingleAmount + "元）");
        }

        // 分配前n-1个红包
        for (int i = 0; i < totalCount - 1; i++) {
            // 计算确保后续红包不低于 globalMinSingleAmount 所需的当前红包最大值
            BigDecimal maxToEnsureNextNotBelowMin = remainingAmount.subtract(globalMinSingleAmount.multiply(new BigDecimal(remainingCount - 1)));

            // 计算当前红包的最小值（基于正常最大值限制）
            BigDecimal minToEnsureNextNotExceedMax = remainingAmount.subtract(globalMaxSingleAmount.multiply(new BigDecimal(remainingCount - 1)));
            BigDecimal minForCurrent = globalMinSingleAmount.max(minToEnsureNextNotExceedMax);

            // 正常情况下的最大值
            BigDecimal maxForCurrent = globalMaxSingleAmount.min(maxToEnsureNextNotBelowMin);

            // 如果正常限制下无法分配，则启用极端情况的最大值（50%）
            if (minForCurrent.compareTo(maxForCurrent) > 0) {
                // 使用极端情况的最大限制（50%）
                BigDecimal extremeMaxSingleAmount = totalAmount.multiply(EXTREME_MAX_RATIO).setScale(SCALE, ROUND_MODE);
                BigDecimal extremeMaxToEnsureNextNotBelowMin = remainingAmount.subtract(globalMinSingleAmount.multiply(new BigDecimal(remainingCount - 1)));
                maxForCurrent = extremeMaxSingleAmount.min(extremeMaxToEnsureNextNotBelowMin);

                // 重新计算最小值
                BigDecimal extremeMinToEnsureNextNotExceedMax = remainingAmount.subtract(extremeMaxSingleAmount.multiply(new BigDecimal(remainingCount - 1)));
                minForCurrent = globalMinSingleAmount.max(extremeMinToEnsureNextNotExceedMax);

                log.warn("红包分配启用极端情况策略，最大限制调整为50%。总金额: {}, 剩余: {}, 剩余个数: {}",
                        totalAmount, remainingAmount, remainingCount);
            }

            // 兜底检查：确保 min <= max 关系
            if (minForCurrent.compareTo(maxForCurrent) > 0) {
                log.warn("红包分配发生兜底冲突，调整策略。总金额: {}, 剩余: {}, 剩余个数: {}", totalAmount, remainingAmount, remainingCount);
                // 如果冲突，说明问题出在输入或前面分配，采用平均值作为最终方案
                BigDecimal avgRemain = remainingAmount.divide(new BigDecimal(remainingCount), SCALE, RoundingMode.DOWN);
                minForCurrent = avgRemain;
                maxForCurrent = avgRemain;
                // 再次检查，如果还是冲突，则直接分配平均值
                if (minForCurrent.compareTo(maxForCurrent) > 0) {
                    minForCurrent = avgRemain;
                    maxForCurrent = avgRemain;
                }
            }

            // 生成随机金额
            BigDecimal currentAmount = getRandomAmount(minForCurrent, maxForCurrent);
            log.debug("分配第 {}/{} 个红包: 金额范围 [{}, {}], 实际分配 {}", i + 1, totalCount, minForCurrent, maxForCurrent, currentAmount);

            // 更新剩余金额和个数
            remainingAmount = remainingAmount.subtract(currentAmount).setScale(SCALE, ROUND_MODE);
            remainingCount--;
            packets.add(currentAmount);
        }

        // 分配最后一个红包（剩余金额）
        log.debug("分配最后一个红包: 金额 {}", remainingAmount);
        packets.add(remainingAmount);

        // 最终校验：确保所有红包都不低于最小值，且总和正确
        validatePacketsWithMinLimitOnly(packets, totalAmount, globalMinSingleAmount);
        return packets;
    }

    /**
     * 最终校验所有红包：确保满足最小限制，且总和正确（不再强制校验最大值限制）
     *
     * @param packets          红包列表
     * @param totalAmount      总金额
     * @param minSingleAmount  单个红包最小金额
     */
    private static void validatePacketsWithMinLimitOnly(List<BigDecimal> packets, BigDecimal totalAmount,
                                                        BigDecimal minSingleAmount) {
        // 1. 校验总和（严格等于总金额，不允许误差）
        BigDecimal sum = BigDecimal.ZERO;
        for (BigDecimal packet : packets) {
            sum = sum.add(packet);
        }
        // 使用 compareTo 进行精确比较，并提供容差（虽然理论上不应该需要），1分钱容差
        BigDecimal tolerance = new BigDecimal("0.01");
        if (sum.subtract(totalAmount).abs().compareTo(tolerance) > 0) {
            throw new RuntimeException("红包总和异常（应为" + totalAmount + "元，实际：" + sum + "元，差值：" + sum.subtract(totalAmount) + "）");
        }

        // 2. 只校验每个红包不低于最小值 (不再校验最大值)
        for (int i = 0; i < packets.size(); i++) {
            BigDecimal packet = packets.get(i);
            boolean isMinViolated = packet.compareTo(minSingleAmount) < 0;

            if (isMinViolated) {
                // 提供更详细的错误信息，包括是第几个红包
                StringBuilder errorMsg = new StringBuilder();
                errorMsg.append("第 ").append(i + 1).append(" 个红包金额 ").append(packet).append("元 ");
                errorMsg.append("小于最小限制 ").append(minSingleAmount).append("元 ");
                errorMsg.append("(总金额: ").append(totalAmount).append(", 个数: ").append(packets.size()).append(")");
                throw new RuntimeException(errorMsg.toString().trim());
            }
        }
    }


    /**
     * 生成指定区间内的随机金额（确保在[min, max]之间）
     *
     * @param min 最小金额 (包含)
     * @param max 最大金额 (包含)
     * @return 随机金额（保留2位小数）
     */
    private static BigDecimal getRandomAmount(BigDecimal min, BigDecimal max) {
        // 如果 min 和 max 相等，直接返回，避免精度问题和随机数生成
        if (min.compareTo(max) == 0) {
            log.trace("getRandomAmount: min equals max ({}), returning directly.", min);
            return min;
        }
        // 转换为“分”（整数）计算，避免小数随机误差
        // 使用 ROUND_DOWN 确保 minFen 对应的金额不大于原始 min
        long minFen = min.multiply(new BigDecimal("100")).setScale(0, RoundingMode.DOWN).longValue();
        // 使用 ROUND_UP 确保 maxFen 对应的金额不小于原始 max
        long maxFen = max.multiply(new BigDecimal("100")).setScale(0, RoundingMode.UP).longValue();

        // 处理 minFen 和 maxFen 相等的情况 (虽然上面已经处理了，但作为双重保险)
        if (minFen == maxFen) {
            return new BigDecimal(minFen).divide(new BigDecimal("100"), SCALE, ROUND_MODE);
        }

        // 使用 ThreadLocalRandom 生成 [minFen, maxFen] 的随机数 (包含边界),注意： +1 保证包含 maxFen
        long randomRange = maxFen - minFen + 1;
        if (randomRange <= 0) {
            // 处理因精度问题导致 range <= 0 的极端情况
            log.warn("getRandomAmount 计算范围异常: min={}, max={}, minFen={}, maxFen={}, range={}", min, max, minFen, maxFen, randomRange);
            // 如果范围异常，返回 min
            return min;
        }
        long randomFen = minFen + ThreadLocalRandom.current().nextLong(randomRange);
        // 转回“元”并保留2位小数
        BigDecimal result = new BigDecimal(randomFen).divide(new BigDecimal("100"), SCALE, ROUND_MODE);
        log.trace("getRandomAmount: generated {} from range [{}, {}]", result, min, max);
        return result;
    }


    /**
     * 最终校验所有红包：确保满足1%最小+30%最大限制，且总和正确
     *
     * @param packets          红包列表
     * @param totalAmount      总金额
     * @param minSingleAmount  单个红包最小金额
     * @param maxSingleAmount  单个红包最大金额
     */
    private static void validateAllPackets(List<BigDecimal> packets, BigDecimal totalAmount,
                                           BigDecimal minSingleAmount, BigDecimal maxSingleAmount) {
        // 1. 校验总和（严格等于总金额，不允许误差）
        BigDecimal sum = BigDecimal.ZERO;
        for (BigDecimal packet : packets) {
            sum = sum.add(packet);
        }
        // 使用 compareTo 进行精确比较，并提供容差（虽然理论上不应该需要），1分钱容差
        BigDecimal tolerance = new BigDecimal("0.01");
        if (sum.subtract(totalAmount).abs().compareTo(tolerance) > 0) {
            throw new RuntimeException("红包总和异常（应为" + totalAmount + "元，实际：" + sum + "元，差值：" + sum.subtract(totalAmount) + "）");
        }

        // 2. 校验每个红包的双限制 (严格抛出异常)
        for (int i = 0; i < packets.size(); i++) {
            BigDecimal packet = packets.get(i);
            boolean isMinViolated = packet.compareTo(minSingleAmount) < 0;
            boolean isMaxViolated = packet.compareTo(maxSingleAmount) > 0;

            if (isMinViolated || isMaxViolated) {
                // 提供更详细的错误信息，包括是第几个红包
                StringBuilder errorMsg = new StringBuilder();
                errorMsg.append("第 ").append(i + 1).append(" 个红包金额 ").append(packet).append("元 ");
                if (isMinViolated) {
                    errorMsg.append("小于最小限制 ").append(minSingleAmount).append("元 ");
                }
                if (isMaxViolated) {
                    errorMsg.append("大于最大限制 ").append(maxSingleAmount).append("元 ");
                }
                errorMsg.append("(总金额: ").append(totalAmount).append(", 个数: ").append(packets.size()).append(")");
                throw new RuntimeException(errorMsg.toString().trim());
            }
        }
    }

    // 为了完整性，保留 main 方法用于测试
    public static void main(String[] args) {
//        System.out.println("=== 普通红包测试 ===");
//        List<BigDecimal> normalRedPackets = getNormalRedPacketAmounts(new BigDecimal("100.00"), 5);
//        System.out.println("普通红包1 (5个): " + normalRedPackets + ", 总和: " + normalRedPackets.stream().reduce(BigDecimal.ZERO, BigDecimal::add));
//
//        List<BigDecimal> normalRedPackets2 = getNormalRedPacketAmounts(new BigDecimal("100.00"), 6);
//        System.out.println("普通红包2 (6个): " + normalRedPackets2 + ", 总和: " + normalRedPackets2.stream().reduce(BigDecimal.ZERO, BigDecimal::add));

        System.out.println("\n=== 拼手气红包测试 ===");
        try {
            List<BigDecimal> randomRedPackets = getRandomRedPacketAmounts(new BigDecimal("100.00"), 5);
            System.out.println("拼手气红包1 (5个): " + randomRedPackets + ", 总和: " + randomRedPackets.stream().reduce(BigDecimal.ZERO, BigDecimal::add));
        } catch (Exception e) {
            System.err.println("拼手气红包1错误: " + e.getMessage());
            e.printStackTrace();
        }

        try {
            List<BigDecimal> randomRedPackets2 = getRandomRedPacketAmounts(new BigDecimal("100.00"), 6);
            System.out.println("拼手气红包2 (6个): " + randomRedPackets2 + ", 总和: " + randomRedPackets2.stream().reduce(BigDecimal.ZERO, BigDecimal::add));
        } catch (Exception e) {
            System.err.println("拼手气红包2错误: " + e.getMessage());
            e.printStackTrace();
        }

        // 测试边界情况
        System.out.println("\n=== 边界情况测试 ===");
        try {
            // 测试最小金额和个数  0.01 * 5 = 0.05
            List<BigDecimal> minCase = getRandomRedPacketAmounts(new BigDecimal("0.05"), 5);
            System.out.println("最小金额边界 (0.05元, 5个): " + minCase + ", 总和: " + minCase.stream().reduce(BigDecimal.ZERO, BigDecimal::add));
        } catch (Exception e) {
            System.err.println("最小金额边界测试错误: " + e.getMessage());
            e.printStackTrace();
        }

        try {
            // 测试接近最大比例的情况  100 * 0.3 = 30
            List<BigDecimal> maxRatioCase = getRandomRedPacketAmounts(new BigDecimal("100.00"), 4);
            System.out.println("较大比例测试 (100元, 4个): " + maxRatioCase + ", 总和: " + maxRatioCase.stream().reduce(BigDecimal.ZERO, BigDecimal::add));
            // 检查是否有超过 30 的
            boolean hasExceeded = maxRatioCase.stream().anyMatch(p -> p.compareTo(new BigDecimal("30.00")) > 0);
            if (hasExceeded) {
                System.err.println("  -> 较大比例测试失败：发现超过30.00的红包");
            } else {
                System.out.println("  -> 较大比例测试通过");
            }
        } catch (Exception e) {
            System.err.println("较大比例测试错误: " + e.getMessage());
            e.printStackTrace();
        }

        // 测试导致之前错误的场景
        System.out.println("\n=== 回归测试 ===");
        boolean allPassed = true;
        try {
            List<BigDecimal> regressionTest1 = getRandomRedPacketAmounts(new BigDecimal("100.00"), 5);
            System.out.println("回归测试1 (100元, 5个): " + regressionTest1 + ", 总和: " + regressionTest1.stream().reduce(BigDecimal.ZERO, BigDecimal::add));
            boolean hasExceeded = regressionTest1.stream().anyMatch(p -> p.compareTo(new BigDecimal("30.00")) > 0);
            if (hasExceeded) {
                System.err.println("  -> 回归测试1失败：发现超过30.00的红包");
                allPassed = false;
            } else {
                System.out.println("  -> 回归测试1通过");
            }
        } catch (Exception e) {
            System.err.println("回归测试1错误: " + e.getMessage());
            e.printStackTrace();
            allPassed = false;
        }

        try {
            List<BigDecimal> regressionTest2 = getRandomRedPacketAmounts(new BigDecimal("100.00"), 6);
            System.out.println("回归测试2 (100元, 6个): " + regressionTest2 + ", 总和: " + regressionTest2.stream().reduce(BigDecimal.ZERO, BigDecimal::add));
            // 100*0.3=30
            boolean hasExceeded = regressionTest2.stream().anyMatch(p -> p.compareTo(new BigDecimal("30.00")) > 0);
            if (hasExceeded) {
                System.err.println("  -> 回归测试2失败：发现超过30.00的红包");
                allPassed = false;
            } else {
                System.out.println("  -> 回归测试2通过");
            }
        } catch (Exception e) {
            System.err.println("回归测试2错误: " + e.getMessage());
            e.printStackTrace();
            allPassed = false;
        }

        if (allPassed) {
            System.out.println("\n=== 所有回归测试通过! ===");
        } else {
            System.out.println("\n=== 存在测试失败! ===");
        }

        // 额外测试：1个红包
        System.out.println("\n=== 特殊情况测试 ===");
        try {
            List<BigDecimal> onePacket = getRandomRedPacketAmounts(new BigDecimal("100.00"), 1);
            System.out.println("单个红包测试 (100元, 1个): " + onePacket + ", 总和: " + onePacket.stream().reduce(BigDecimal.ZERO, BigDecimal::add));
            if (onePacket.get(0).compareTo(new BigDecimal("100.00")) == 0) {
                System.out.println("  -> 单个红包测试通过");
            } else {
                System.err.println("  -> 单个红包测试失败");
            }
        } catch (Exception e) {
            System.err.println("单个红包测试错误: " + e.getMessage());
            e.printStackTrace();
        }

        // 额外测试：2个红包
        System.out.println("\n=== 特殊情况测试 ===");
        try {
            List<BigDecimal> onePacket = getRandomRedPacketAmounts(new BigDecimal("100.00"), 2);
            System.out.println("2个红包测试 (100元, 2个): " + onePacket + ", 总和: " + onePacket.stream().reduce(BigDecimal.ZERO, BigDecimal::add));
            if (onePacket.get(0).compareTo(new BigDecimal("100.00")) == 0) {
                System.out.println("  -> 2个红包测试通过");
            } else {
                System.err.println("  -> 2个红包测试失败");
            }
        } catch (Exception e) {
            System.err.println("2个红包测试错误: " + e.getMessage());
            e.printStackTrace();
        }

        // 额外测试：3个红包
        System.out.println("\n=== 特殊情况测试 ===");
        try {
            List<BigDecimal> onePacket = getRandomRedPacketAmounts(new BigDecimal("100.00"), 3);
            System.out.println("3个红包测试 (100元, 3个): " + onePacket + ", 总和: " + onePacket.stream().reduce(BigDecimal.ZERO, BigDecimal::add));
            if (onePacket.get(0).compareTo(new BigDecimal("100.00")) == 0) {
                System.out.println("  -> 3个红包测试通过");
            } else {
                System.err.println("  -> 3个红包测试失败");
            }
        } catch (Exception e) {
            System.err.println("3个红包测试错误: " + e.getMessage());
            e.printStackTrace();
        }
    }

}
